<!-- 示例: 特定元素必须作为子元素 -->
<template>
  <div>
    <p>{{ arr2 }}</p>
    <p><strong>张三,李四,王五,赵六 这些元素无法直接拖动到右侧，只能作为 容器元素 的子元素</strong></p>
    <div class="container">
      <draggable :list="arr" :group="{name:'test',pull:'clone'}" animation="300" class="draggablePanel" :move="onMove"
                 @end="onEnd" :clone="onClone">
        <transition-group>
          <div class="item" v-for="item in arr" :key="item.id">{{ item.name }}</div>
        </transition-group>
      </draggable>
      <draggable :list="arr2" group="test" animation="300" class="draggablePanel">
        <transition-group>
          <template v-for="(item,index) in arr2">
            <div v-if="item.type==='normal'" class="item" :key="index">{{ item.name }}</div>
            <template v-else>
              <draggable :list="item.children" group="test" animation="300" class="subContainer"
                         :key="index">
                <div class="item" v-for="(subItem,pos) in item.children" :key="pos">{{ subItem.name }}</div>
              </draggable>
            </template>
          </template>
        </transition-group>
      </draggable>
    </div>
  </div>
</template>

<script>
import {defineComponent, reactive, ref} from "vue";
import {VueDraggableNext as draggable} from 'vue-draggable-next'

export default defineComponent({
  setup() {
    const arr = reactive([
      {id: 1, name: "容器元素", type: 'container', children: []},
      {id: 2, name: "李四", type: 'normal', children: []},
      {id: 3, name: "王五", type: 'normal', children: []},
      {id: 4, name: "赵六", type: 'normal', children: []}
    ]);
    const arr2 = reactive([]);
    const moveType = ref(null);
    const onMove = (e, originalEvent) => {
      // 记录当前拖动元素的类型
      if (e.draggedContext.element) {
        moveType.value = e.draggedContext.element.type
      }
      return true;
    }
    const onEnd = (e) => {
      // console.log(e)
      console.log('end', e, e.to, e.to.classList)
      if (null !== moveType.value && moveType.value === 'normal') {
        // 当前拖动元素的类型为 normal
        if (!(e.to && e.to.classList && e.to.classList.length > 0 && e.to.classList.contains('subContainer'))) {
          // 目标组件是容器组件
          // 当前拖动的元素为普通组件, 但目标组件并非子容器, 所以删除
          arr2.splice(e.newDraggableIndex, 1)
        }
      }
    }
    const onClone = (sourceObj) => {
      return {...sourceObj, children: []}
    }
    return {arr, arr2, onMove, onEnd, onClone}
  },
  components: {
    draggable
  }
})
</script>

<style scoped>
.container {
  width: 100%;
}

.draggablePanel {
  box-sizing: border-box;
  height: 300px;
  width: 50%;
  float: left;
  border: 1px solid #eee;
}

.draggablePanel div {
  width: 100%;
  height: 30px;
  line-height: 30px;
  margin-bottom: 5px;
  padding-left: 20px;
}

div.subContainer {
  box-sizing: border-box;
  height: 100px;
  border: 2px dashed #eee;
}
</style>